package com.heu.miaosha.service.impl;

import com.heu.miaosha.dao.PromoDOMapper;
import com.heu.miaosha.dataobject.PromoDO;
import com.heu.miaosha.error.BusinessException;
import com.heu.miaosha.error.EmBusinessError;
import com.heu.miaosha.service.ItemService;
import com.heu.miaosha.service.PromoService;
import com.heu.miaosha.service.UserService;
import com.heu.miaosha.service.model.ItemModel;
import com.heu.miaosha.service.model.PromoModel;
import com.heu.miaosha.service.model.UserModel;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author: lidong
 * @description
 * @date: 2023/3/8 9:58
 */
@Service
public class PromoServiceImpl implements PromoService {

    @Autowired
    private PromoDOMapper promoDOMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ItemService itemService;
    @Autowired
    private UserService userService;

    @Override
    public PromoModel getPromoByItemId(Integer itemId) {
        PromoDO promoDO = promoDOMapper.selectByItemId(itemId);
        PromoModel promoModel = convertFromDataObject(promoDO);
        if (promoModel == null) {
            return null;
        }



        if (promoModel.getStartDate().isAfterNow()){
            promoModel.setStatus(1);
        } else if (promoModel.getEndDate().isBeforeNow())   {
            promoModel.setStatus(3);
        }else{
            promoModel.setStatus(2);
        }


        return promoModel;
    }

    @Override
    public void publishPromo(Integer promoId) {
        PromoDO promoDO = promoDOMapper.selectByPrimaryKey(promoId);
        if (promoDO.getItemId()==null || promoDO.getItemId().intValue() == 0){
            return;
        }

        ItemModel itemModel = itemService.getItemById(promoDO.getItemId());
        redisTemplate.opsForValue().set("promo_item_stock_"+itemModel.getId(),itemModel.getStock());


        //将大闸限制数字设置到redis内部
        redisTemplate.opsForValue().set("promo_door_count_"+promoId , itemModel.getStock().intValue()*5);
    }

    @Override
    public String generateSecondKillToken(Integer promoId , Integer itemId ,Integer userId) {
        if (redisTemplate.hasKey("promo_item_stock_invalid_"+itemId)){
            return null;
        }


        PromoDO promoDO = promoDOMapper.selectByPrimaryKey(promoId);
        PromoModel promoModel = convertFromDataObject(promoDO);
        if (promoModel == null) {
            return null;
        }


        if (promoModel.getStartDate().isAfterNow()){
            promoModel.setStatus(1);
        } else if (promoModel.getEndDate().isBeforeNow())   {
            promoModel.setStatus(3);
        }else{
            promoModel.setStatus(2);
        }
        if (promoModel.getStatus()  != 2){
            return null;
        }
        ItemModel itemModel = itemService.getItemByIdInCache(itemId);
        if (itemModel == null){
           return null;
        }

        UserModel userModel = userService.getUserByIdInCache(userId);
        if (userModel == null){
            return null;

        }
        //获取秒杀大闸的count数量
        Long result = redisTemplate.opsForValue().increment("promo_door_count_" + promoId, -1);
        if (result < 0){
            return  null;
        }

        String token = UUID.randomUUID().toString().replace("-","");

        redisTemplate.opsForValue().set("promo_token_"+promoId+"_userid_"+userId+"_itemid_"+itemId,token);
        redisTemplate.expire("promo_token_"+promoId+"_userid_"+userId+"_itemid_"+itemId,5,TimeUnit.MINUTES);

        return token;
    }


    private PromoModel convertFromDataObject(PromoDO promoDO){
        if (promoDO == null){
            return null;
        }
        PromoModel promoModel = new PromoModel();
        BeanUtils.copyProperties(promoDO,promoModel);
        promoModel.setStartDate(new DateTime(promoDO.getStartDate()));
        promoModel.setEndDate(new DateTime(promoDO.getEndDate()));
        promoModel.setPromoItemPrice(new BigDecimal(promoDO.getPromoItemPrice()));

        return promoModel;
    }
}
